﻿using System.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net;

namespace Albatross.WPF.Common.PubSub {
	public class Subscription<T> : ISubscription<T> {
		protected ILog Log;
		public string Topic { get; private set; }
		public object Subscriber { get; private set; }
		public IPublisher Publisher { get; private set; }
		public Type MsgType { get { return typeof(T); } }

		public event MsgReceivedEventHandler<T> MsgReceived;

		public virtual void Init(IPublisher publisher, object subscriber, string topic) {
			if (Publisher == null) {
				Publisher = publisher;
				Subscriber = subscriber;
				Topic = topic;
				Log = LogManager.GetLogger(string.Format("Subscription:{0} for {1}" , topic, MsgType.FullName));
			} else {
				throw new Exception("Subscription object has already been initialized");
			}
		}

		protected void OnMsgReceived(object sender, T msg) {
			MsgReceivedEventHandler<T> handle = MsgReceived;
			if (handle != null) {
				try {
					handle(sender, msg);
				} catch (Exception err) {
					Log.Error(err);
				}
			}
		}

		public virtual void Invoke(object sender, object msg) {
			OnMsgReceived(sender, Convert(msg));
		}

		public void Dispose() {
			if (Publisher != null) {
				Publisher.Unsubscribe(this);
				Publisher = null;
			}
			MsgReceived = null;
		}
		
		public virtual bool TypeCheck(object msg) {
			if (msg == null) {
				return true;
			} else {
				return msg is T;
			}
		}

		public virtual T Convert(object msg) {
			if (msg == null) {
				return default(T);
			} else {
				return (T)msg;
			}
		}
	}
}
